package com.liruo.treasureattic.gateway.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.liruo.treasureattic.common.httpmsg.exception.CommonResultException;
import com.liruo.treasureattic.common.httpmsg.result.BaseResponse;
import com.liruo.treasureattic.common.httpmsg.result.Errno;
import com.liruo.treasureattic.gateway.model.GlobalFilterOrder;
import com.liruo.treasureattic.gateway.util.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * 用于网关的全局异常处理
 * @Order(-1)：优先级一定要比ResponseStatusExceptionHandler低
 */
@Slf4j
@Order(GlobalFilterOrder.GLOBAL_EXCEPTION_HANDLER)
@Component
public class GlobalErrorExceptionHandler implements ErrorWebExceptionHandler {

	@Resource
	private ObjectMapper objectMapper;

	@SuppressWarnings("NullableProblems")
	@Override
	public Mono<Void> handle( ServerWebExchange exchange, Throwable err) {
		ServerHttpResponse response = exchange.getResponse();
		if (response.isCommitted()) {
			return Mono.error(err);
		}
		log.info(err.getMessage());
		err.printStackTrace();
		BaseResponse<String> baseResp = null;
		if (err instanceof ResponseStatusException) {
			HttpStatus status = ((ResponseStatusException) err).getStatus();
			response.setStatusCode(status);
			baseResp = BaseResponse.fail(status.value(),status.getReasonPhrase());
		}else if(err instanceof CommonResultException){
			CommonResultException commErr = (CommonResultException) err;
			baseResp = BaseResponse.fail(commErr.getCode(),commErr.getMessage());
		}else {
			baseResp = BaseResponse.fail(Errno.SYSTEM,"can not find the err type,errmsg = " + err.getMessage());
		}
		baseResp.setData(baseResp.getData());
		return HttpUtil.writeJsonResultAndHandlerJacksonErrWithResult(
				objectMapper,log,exchange.getResponse(),baseResp
		);
	}
}